package com.xingchi.tornado.utils;

import com.xingchi.tornado.jackson.serializer.datamask.DesensitizeType;
import lombok.experimental.UtilityClass;
import org.springframework.util.StringUtils;

/**
 * 数据脱敏工具类
 *
 * @author xingchi
 * @date 2024/7/23 11:05
 */
@UtilityClass
public class DesensitizeUtil {

    /**
     * 根据脱敏类型进行脱敏处理
     *
     * @param value 原始值
     * @param type 脱敏类型
     * @return 脱敏后的值
     */
    public String desensitize(String value, DesensitizeType type) {
        if (StringUtils.isEmpty(value)) {
            return value;
        }

        switch (type) {
            case NAME:
                return desensitizeName(value);
            case MOBILE_PHONE:
                return desensitizeMobilePhone(value);
            case EMAIL:
                return desensitizeEmail(value);
            case ID_CARD:
                return desensitizeIdCard(value);
            case BANK_CARD:
                return desensitizeBankCard(value);
            case ADDRESS:
                return desensitizeAddress(value);
            case PASSWORD:
                return desensitizePassword(value);
            case IP:
                return desensitizeIp(value);
            default:
                return value;
        }
    }

    /**
     * 自定义脱敏
     *
     * @param value 原始值
     * @param prefixKeep 前置保留长度
     * @param suffixKeep 后置保留长度
     * @param replaceChar 替换字符
     * @return 脱敏后的值
     */
    public String desensitizeCustom(String value, int prefixKeep, int suffixKeep, char replaceChar) {
        if (StringUtils.isEmpty(value)) {
            return value;
        }

        int length = value.length();

        // 如果原始值长度小于等于前后保留长度之和，则直接返回替换字符
        if (length <= prefixKeep + suffixKeep) {
            return String.valueOf(replaceChar).repeat(length);
        }

        // 构建脱敏字符串
        StringBuilder result = new StringBuilder();
        result.append(value, 0, prefixKeep);
        result.append(String.valueOf(replaceChar).repeat(length - prefixKeep - suffixKeep));
        result.append(value.substring(length - suffixKeep));

        return result.toString();
    }

    /**
     * 姓名脱敏
     * 规则：只显示第一个汉字，其他用*代替
     *
     * @param name 姓名
     * @return 脱敏后的姓名
     */
    public String desensitizeName(String name) {
        if (StringUtils.isEmpty(name)) {
            return name;
        }

        return desensitizeCustom(name, 1, 0, '*');
    }

    /**
     * 手机号脱敏
     * 规则：前3后4，中间用*代替
     *
     * @param mobilePhone 手机号
     * @return 脱敏后的手机号
     */
    public String desensitizeMobilePhone(String mobilePhone) {
        return desensitizeCustom(mobilePhone, 3, 4, '*');
    }

    /**
     * 邮箱脱敏
     * 规则：邮箱前缀显示前3个字符，后面用*代替，@及后面的地址显示
     *
     * @param email 邮箱
     * @return 脱敏后的邮箱
     */
    public String desensitizeEmail(String email) {
        if (StringUtils.isEmpty(email) || !email.contains("@")) {
            return email;
        }

        int atIndex = email.indexOf('@');
        String prefix = email.substring(0, atIndex);
        String suffix = email.substring(atIndex);

        return desensitizeCustom(prefix, 3, 0, '*') + suffix;
    }

    /**
     * 身份证号脱敏
     * 规则：前6后4，中间用*代替
     *
     * @param idCard 身份证号
     * @return 脱敏后的身份证号
     */
    public String desensitizeIdCard(String idCard) {
        return desensitizeCustom(idCard, 6, 4, '*');
    }

    /**
     * 银行卡号脱敏
     * 规则：前6后4，中间用*代替
     *
     * @param bankCard 银行卡号
     * @return 脱敏后的银行卡号
     */
    public String desensitizeBankCard(String bankCard) {
        return desensitizeCustom(bankCard, 6, 4, '*');
    }

    /**
     * 地址脱敏
     * 规则：只显示到地区，不显示详细地址
     *
     * @param address 地址
     * @return 脱敏后的地址
     */
    public String desensitizeAddress(String address) {
        if (StringUtils.isEmpty(address)) {
            return address;
        }

        // 简单实现，保留前6个字符
        int length = address.length();
        if (length <= 6) {
            return address;
        }

        return address.substring(0, 6) + "******";
    }

    /**
     * 密码脱敏
     * 规则：全部用*代替
     *
     * @param password 密码
     * @return 脱敏后的密码
     */
    public String desensitizePassword(String password) {
        if (StringUtils.isEmpty(password)) {
            return password;
        }

        return "*".repeat(6);
    }

    /**
     * IP地址脱敏
     * 规则：最后一段用*代替
     *
     * @param ip IP地址
     * @return 脱敏后的IP地址
     */
    public String desensitizeIp(String ip) {
        if (StringUtils.isEmpty(ip)) {
            return ip;
        }

        int lastDotIndex = ip.lastIndexOf('.');
        if (lastDotIndex == -1) {
            return ip;
        }

        return ip.substring(0, lastDotIndex + 1) + "*";
    }
}
